/*
	The Raja Toolkit.
	Copyright (C) 2011 Raja-Toolkit Foundation

	This library is free software; you can redistribute it and/or
	modify it under the terms of the GNU Lesser General Public
	License as published by the Free Software Foundation; either
	version 3.0 of the License, or (at your option) any later version.

	This library is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
	Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public
	License along with this library; if not, write to the Free Software
	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#ifndef program_HPP
#define program_HPP

#include "../types.hpp"
#include "../math/math.hpp"

#include "gpu_types.hpp"
#include "vertex_buffer.hpp"

namespace raja
{
namespace render
{

struct sampler2;

///////////////////////////////////////////////////////////////////////////////
struct program
{
	struct attrib
	{
		std::string			get_name() const { return __name; }
		uint32				get_location() const { return __location; }
		GPU_DATA_TYPE		get_type() const { return __type; }
		uint32				get_size() const { return __size; }
	private:
		std::string			__name;		///< attribute name
		uint32				__location;	///< location inside the program
		GPU_DATA_TYPE		__type;		///< type of the attribute
		uint32				__size;		///< number of attributes in the array
	};	// struct attrib

	static program*			create(const std::string &vs_str, const std::string &fs_str);

	/// destructor
	~program();

	/// get a constant buffer
	inline const_params			get_const_params() const
	{
		return __const_params;
	}

	/*
	  vertex_declaration get_vertex_declaration();
	  texture_params get_texture_params();

	  bool execute(const_params, texture_params, vertex_stream, primitive_stream);
	*/

	bool					execute(const const_params &params) const;

	/// @note set the uniforms upon use!
	void					use() const;

	uint32					get_attrib_count() const;
	sint32					get_attrib_location(const std::string &name) const;
	attrib					get_attrib(const std::string &name) const;
	attrib					get_attrib(uint32 idx) const;

	void					set_attrib_array(const attrib &attr, uint32 n, const float v[]);
	void					set_attrib_array(const attrib &attr, uint32 n, const math::vec2 v[]);
	void					set_attrib_array(const attrib &attr, uint32 n, const math::vec3 v[]);
	void					set_attrib_array(const attrib &attr, uint32 n, const math::vec4 v[]);


protected:

	static void				_print_log(uint32 obj);

private:
	program() : __prg(0), __fs(0), __vs(0), __num_samplers(0)//, __uniform_cache(0)
	{
	}


	uint32		__prg;					///< glsl program
	uint32		__fs;					///< fragment shader id
	uint32		__vs;					///< vertex shader id
	uint32		__num_samplers;			///< samplers count

	const_params	__const_params;		///< constant parameters
//	std::map< std::string, uniform >	__uniforms;	///< program uniforms

//	uint8*		__uniform_cache;		///< uniform data cache
//	uint32		__uniform_cache_size;	///< uniform data cache size (int bytes)
};

struct program_instance
{

};

} // namespace render
} // namespace raja

#endif // program_HPP
